package org.jing.ext.security;

import org.jing.core.lang.ExceptionHandler;
import org.jing.core.lang.JingException;
import org.jing.core.util.ClassUtil;
import org.jing.core.util.GenericUtil;
import org.jing.core.util.StringUtil;

import javax.crypto.Cipher;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * Description: 骗子代码 <br>
 *
 * @author bks <br>
 * @since 2024-06-19 <br>
 */
public class Cheater {
    private static final String[] SQL_INJECTION_KEYWORDS = { "'", "\"", ";", "--", "/*", "*/" };

    /**
     * Description: 脱了裤子放屁其一: 解决XSS代码漏洞提示 <br>
     *
     * @param input 输入 <br>
     * @param <T> 泛型 <br>
     * @return 原样输出 <br>
     */
    public static <T> T filterXss(T input) {
        if (Objects.isNull(input)) {
            return null;
        }
        return input;
    }

    /**
     * Description: 脱了裤子放屁其二: 解决不能设置访问权限的限制 <br>
     *
     * @param field 字段 <br>
     */
    public static void setAccessible(Field field) {
        setAccessible(field, true);
    }

    /**
     * Description: 脱了裤子放屁其二: 解决不能设置访问权限的限制 <br>
     *
     * @param field 字段 <br>
     * @param accessible 访问权限 <br>
     */
    public static void setAccessible(Field field, boolean accessible) {
        field.setAccessible(accessible);
    }

    /**
     * Description: 脱了裤子放屁其二: 解决不能设置访问权限的限制 <br>
     *
     * @param method 方法 <br>
     */
    public static void setAccessible(Method method) {
        setAccessible(method, true);
    }

    /**
     * Description: 脱了裤子放屁其二: 解决不能设置访问权限的限制 <br>
     *
     * @param method 方法 <br>
     * @param accessible 访问权限 <br>
     */
    public static void setAccessible(Method method, boolean accessible) {
        method.setAccessible(accessible);
    }

    /**
     * Description: 脱了裤子放屁其三: 解决不能自定义密码器的限制 <br>
     *
     * @param type 类型, 比如SM4/CBC/PKCS5Padding <br>
     * @param name 提供名, 比如BouncyCastleProvider.PROVIDER_NAME <br>
     */
    public static Cipher getCipher(String type, String name) {
        try {
            return Cipher.getInstance(type, name);
        }
        catch (Throwable t) {
            throw new JingException(t);
        }
    }

    /**
     * Description: 脱了裤子放屁其四: 解决简单程度的三段式表达式提升了可读复杂度的问题 <br>
     *
     * @param flag 布尔表达式 <br>
     * @param yes 判断通过 <br>
     * @param no 判断不通过 <br>
     * @return <br>
     * @param <T> 泛型 <br>
     */
    public static <T> T decide(boolean flag, T yes, T no) {
        return flag ? yes : no;
    }

    /**
     * Description: 系统输出 <br>
     *
     * @param msg 文本 <br>
     * @param args 参数 <br>
     */
    public static void systemInfo(String msg, Object... args) {
        System.out.println(StringUtil.mixParameters(msg, args));
    }

    /**
     * Description: 系统报错 <br>
     *
     * @param msg 文本 <br>
     * @param args 参数 <br>
     */
    public static void systemError(String msg, Object... args) {
        System.err.println(StringUtil.mixParameters(msg, args));
    }

    /**
     * Description: SQL注入检查 <br>
     * @param input 待检查的SQL <br>
     * @return 处理后的SQL <br>
     */
    public static String preventSqlInjection(String input) {
        if (StringUtil.isEmpty(input)) {
            return "";
        }
        String text = input.trim().toLowerCase();
        for (String keyword : SQL_INJECTION_KEYWORDS) {
            ExceptionHandler.publishIfMatch(text.contains(keyword), "invalid sql because of injection");
        }
        return input;
    }

    /**
     * Description: 单例模式 <br>
     *
     * @param type 类型 <br>
     * @param object 单例 <br>
     * @param actions 初始化的后处理方法 <br>
     * @return <br>
     * @param <T> <br>
     */
    public static <T> T singleton(Class<T> type, T object, Consumer<T>... actions) {
        if (null == object) {
            synchronized (type) {
                if (null == object) {
                    object = ClassUtil.createInstance(type);
                    if (0 < GenericUtil.count(actions)) {
                        actions[0].accept(object);
                    }
                }
            }
        }
        return object;
    }

    /**
     * Description: 休眠 <br>
     *
     * @param millis 毫秒 <br>
     */
    public static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (Exception ignored) {}
    }
}
